package edu.psu.geovista.app.pcp.plot.layer;

import edu.psu.geovista.app.pcp.plot.services.CorrelationResult;
import edu.psu.geovista.app.pcp.toolkits.Math.JMath;
import edu.psu.geovista.app.pcp.toolkits.java2d.Java2DToolkit;
import edu.psu.geovista.app.plot.axis.AxisList;
import edu.psu.geovista.app.plot.axis.XAxis;
import edu.psu.geovista.app.plot.axis.YAxis;
import edu.psu.geovista.app.plot.layer.Layer;

import java.awt.*;
import java.util.ArrayList;
import java.util.Iterator;

/*
 * GeoVISTA Center (Penn State, Dept. of Geography)
 * Copyright (c), 2003-2011,  Jin Chen and Alan M. MacEachren, GeoVISTA Center, Penn State University
 * All Rights Researved.
 *
 * This library is developed and distributed for free usage,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * You can redistribute and/or modify it under the terms of the
 * Simplified BSD License
 *
 *
 *
 *
 *
 *
 *
 * Description:
 *      - manage layout of axis position(x,y)
 *      - manage gap between axis
 *      - manage layout of axis orders
 *      - configure visibility of axis
 *      - create,add/remove axis
 *
 * Date: May 30, 2003
 * Time: 12:38:31 PM
 * @author Jin Chen
 */

public class AxisLayer extends RuntimeLayer {
    public static final boolean DEBUG = false;
    //BasicPcpUI owner;
    private boolean showCorrelation;
    //private Dimension size;
    public AxisLayer(String name,AxisList yaxisList, XAxis xaxis, Dimension size) {

        //this.plot = pcp;

        this.yaxisList=yaxisList;//pcp.getYaxisList() ;
        this.xaxis =(edu.psu.geovista.app.plot.axis.XAxisOrder) xaxis;//pcp.getXaxis() ;
        this.setSize(size ) ;
        //this.setLevel(Layer.ABOVE_MIDDLE) ;

        this.setName(name );
        this.setType(Layer.TYPE_AXIS );

        this.configInfo =new AxisLayerConfigInfo();
        this.paintLayer() ;//do first paint

    }
    /**************************************************
     *                paint mode
     ***************************************************/
    /**
     * A layer may have different appearance, this method control how they looks like variously
     * In simple mode, YAxis will be in dark color and  not have label
      * @param mode
     */
    public void setPaintMode(int mode){
        AxisList yaxisList =this.yaxisList ;
        if(mode==Layer.PAINT_MODE_SIMPLE){
            yaxisList.setAxesPaintMode(YAxis.PAINT_MODE_SIMPLE);
            Color color=new Color(132,155,166);
            setAConfigInfo(ConfigInfo.Attr_COLOR ,color);
        }
        else if(mode==Layer.PAINT_MODE_FULL){
             yaxisList.setAxesPaintMode(YAxis.PAINT_MODE_FULL);
             setAConfigInfo(ConfigInfo.Attr_COLOR ,Color.yellow );
        }
    }

    /********************************************************************
     *                operation on axis
     ********************************************************************/
    /**
     * exchange the location value YAxis.x of the <from> and <to>.
     * @param from
     * @param to
     */
    public void switchAxisX(int from, int to) {
        //dp{
        if (DEBUG){
            System.out.println("Switch "+from +" to "+to);
        }//dp}
        YAxis frmAx=this.yaxisList.getAxis(from);
        YAxis toAx=this.yaxisList.getAxis(to);

        //repaint axislayer regoin
        //this.cleanAxis(frmAx);
        //this.cleanAxis(toAx);
        this.clearLayer() ;
        //this.image=BasicLayer.getBlankImage(this.getSize() );


        int toX = this.xaxis.getLocX(toAx);
        int toY = frmAx.getLocation().y;

        int fromX = this.xaxis.getLocX(frmAx);
        int fromY = toAx.getLocation().y;


        frmAx.setIndex(to);
        frmAx.setAxisLocation(toX,toY);

        toAx.setIndex(from);
        toAx.setAxisLocation(fromX,fromY);

        //int[] axs=new int[]{from,to};
        //this.getLineLayer().repaintAxis(axs);
        this.paintLayer() ;

        //repaint linelayer regoin


    }

    public void repaintLayer() {
        //this.cleanAxis(axis);
        this.clearLayer() ;
        this.paintLayer() ;
    }
    public void paintLayer(){

    }
    /*
    private void cleanAxis(YAxis axis){
        Rectangle rect=this.getAxisRegoin(axis);
        this.cleanRegoin(rect);
    }   */

    public void moveAxisY(int from, int to) {
    }

   /* public void setAxisLocationX(YAxis axis, int x){
        axis.getLocation().x = x;
    }

    public void setAxisLocationY(YAxis axis, int y){
        axis.getLocation().y = y;
    }*/

    public void setAxisTickExtreme(YAxis[] axis, float max, float min) {
    }

    public void setAxisTickRange(YAxis[] axis, float max, float min) {
        //Not change scale, hidden some lines
    }

    public void addAxis(int index) {
    }

    public void removeAxis(int index) {
    }

    public void showBoxPlot() {
    }

    public void aliginBoxPlot() {
    }


    /*******************************************************************************************************
     *                paint
     *******************************************************************************************************/

    protected  void paintComponent(Graphics g) {
        /*Color oldc = g.getColor();
        Color color=(Color) this.configInfo.getConfig(ConfigInfo.COLOR );
        if(color!=null)//color=Color.black ;
                g.setColor(color);*/

        this.drawAllAxis(g);
        if(this.isShowCorrelation())
            paintCorrelation(g);

        //g.setColor(oldc);
    }
    private void drawAllAxis(Graphics g) {
        Boolean showX=(Boolean) this.getConfigInfo().getConfig(AxisLayerConfigInfo.ShowXAxis );
        Boolean showY=(Boolean) this.getConfigInfo().getConfig(AxisLayerConfigInfo.ShowYAxis );
        boolean shx=showX.booleanValue() ;
        boolean shy=showY.booleanValue() ;
        //System.out.println(" *** drawAllAxis ***->");
        //Collections.sort(this.axisList );
        if(shy){
            Iterator iter=yaxisList.iterator() ;
            while(iter.hasNext() ){
                YAxis axis=(YAxis)iter.next() ;
                axis.paintComponent(g);
                //System.out.println("try to paint "+axis.getName() + " index "+axis.getIndex() + " loc :"+axis.getLocation().x);
            }
        }
        if(shx)
            this.xaxis.paintComponent(g);
        //System.out.println(" *** drawAllAxis ***<-");
    }

    private void updateAllAxisConfigInfo(){
        ConfigInfo configInfo = this.getConfigInfo();
        Font titleFont=(Font) configInfo.getConfig(AxisLayerConfigInfo.YAxisTitleFont );
        Boolean showLabel=(Boolean) configInfo.getConfig(AxisLayerConfigInfo.ShowLabel );
        Boolean showYFoot=(Boolean) configInfo.getConfig(AxisLayerConfigInfo.ShowYAxisFoot );
        Boolean showFilterTick=(Boolean) configInfo.getConfig(AxisLayerConfigInfo.ShowFilterTick );
        for (Iterator iterator = yaxisList.iterator(); iterator.hasNext();) {
            YAxis yAxis = (YAxis) iterator.next();
            if(yAxis!=null)  {
            yAxis.setShowLabel(showLabel.booleanValue() );
            yAxis.setHeaderFont(titleFont);
            yAxis.setShowFooter(showYFoot.booleanValue() );
            yAxis.setShowFilterTick(showFilterTick);
            }
        }
    }

    /*******************************************************************************************************
     *                correlation
     *******************************************************************************************************/
    private void paintCorrelation(Graphics g){

        ArrayList axisList = yaxisList.getIndexSortAxisList();
        Color bgc=new Color(200,200,200,150);
        Color fc=Color.green;
        for (int i=1;i<axisList.size();i++){
            YAxis paxis=(YAxis) axisList.get(i-1);
            YAxis axis=(YAxis) axisList.get(i);
            //double correlation = this.ui.getPlot().getCorrelation(paxis,axis);
            CorrelationResult correlation = this.ui.getService().getCorrelation(paxis,axis);
            int pax=paxis.getLocation().x;
            int ax=axis.getLocation().x;
            int gap=ax-pax;
            int x=ax-gap/2;
            Rectangle footOutLine = axis.getFooter().getOutLine();
            int y=footOutLine.y+footOutLine.height +5;
            String cr="";

            double crvalue=correlation.getValue();
            int numOfInvalid=correlation.getNumOfInvalid();

            if(!Double.isNaN(crvalue)){
                cr=JMath.getRoundValue(crvalue,2);
            }
            else{
                cr="invalid";
            }
            if(numOfInvalid>0){
                cr=cr+"("+numOfInvalid+")";
            }

            Java2DToolkit.paintTooltip(g,cr,x,y,null,fc,bgc);
           // paintString(g,cr,x,y,null,);

        }

    }



    /*public BasicPcpUI getOwner() {
        return owner;
    }

    public void setOwner(BasicPcpUI owner) {
        this.owner = owner;
    }*/

    public boolean isShowCorrelation() {
        return showCorrelation;
    }

    public void setShowCorrelation(boolean showCorrelation) {
        this.showCorrelation = showCorrelation;
    }

    /*******************************************************************************************************
     *                properties
     *******************************************************************************************************/
    /*
    public  Dimension getSize() {
        return size;
    }

    private  void setSize(Dimension size) {
        this.size = size;
    }         */
    // should removed
    public AxisList getAxisList() {
        return yaxisList;
    }
    /*
    public DataLayer getLineLayer() {
       return (DataLayer)this.getLayer(Layer.LINE_LAYER ) ;
    }               */
    /*******************************************************************************************************
     *                config
     *******************************************************************************************************/
    public void setAConfigInfo(String key, Object value) {
            super.setAConfigInfo(key, value);
            if(key.equals(AxisLayerConfigInfo.ShowLabel)
             ||key.equals(AxisLayerConfigInfo.YAxisTitleFont)
             ||key.equals(AxisLayerConfigInfo.ShowYAxisFoot)
             ||key.equals(AxisLayerConfigInfo.ShowFilterTick)
             /*||key.equals(AxisLayerConfigInfo.YAxisValueUnit )  */ ){
                 updateAllAxisConfigInfo();// 
            }
        }
    public static class AxisLayerConfigInfo extends DefaultConfigInfo{
       // 
       public static final String ShowYAxis="shya";
       public static final String ShowXAxis="shxa";
       public static final String ShowLabel="shl";
       public static final String ShowYAxisFoot="shyft";
       public static final String ShowFilterTick="shftk";//show range ticks
       public static final String YAxisTitleFont="ytfont";
       public static final String YAxisValueUnit="yvu";


        public AxisLayerConfigInfo() {

            super();
            this.configs.put(ShowYAxis,Boolean.TRUE );
            this.configs.put(ShowXAxis,Boolean.TRUE );
            this.configs.put(ShowLabel,Boolean.TRUE );
            this.configs.put(ShowYAxisFoot,Boolean.TRUE );
            this.configs.put(ShowFilterTick,Boolean.TRUE );
            this.configs.put(YAxisTitleFont,new Font("Monospaced",Font.BOLD,15 ));
            this.configs.put(ConfigInfo.Attr_COLOR,Color.yellow ); // color is eventually set at Layer.paintLayer()
            this.configs.put(YAxisValueUnit,new Integer(1));
        }

    }
}
